///*
// * Licensed to the Apache Software Foundation (ASF) under one
// * or more contributor license agreements.  See the NOTICE file
// * distributed with this work for additional information
// * regarding copyright ownership.  The ASF licenses this file
// * to you under the Apache License, Version 2.0 (the
// * "License"); you may not use this file except in compliance
// * with the License.  You may obtain a copy of the License at
// *
// *   http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing,
// * software distributed under the License is distributed on an
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// * KIND, either express or implied.  See the License for the
// * specific language governing permissions and limitations
// * under the License.
// */
//package org.apache.felix.main;
//
//import java.io.*;
//import java.net.MalformedURLException;
//import java.net.URL;
//import java.util.*;
//import org.apache.felix.framework.Felix;
//import org.apache.felix.framework.util.FelixConstants;
//import org.apache.felix.framework.util.Util;
//import org.osgi.framework.Constants;
//import org.osgi.framework.launch.Framework;
//
///**
// * <p>
// * This class is the default way to instantiate and execute the framework. It is not
// * intended to be the only way to instantiate and execute the framework; rather, it is
// * one example of how to do so. When embedding the framework in a host application,
// * this class can serve as a simple guide of how to do so. It may even be
// * worthwhile to reuse some of its property handling capabilities.
// * </p>
//**/
//public class Main
//{
//    /**
//     * The property name used to specify an URL to the system
//     * property file.
//    **/
//    public static final String SYSTEM_PROPERTIES_PROP = "felix.system.properties";
//    /**
//     * The default name used for the system properties file.
//    **/
//    public static final String SYSTEM_PROPERTIES_FILE_VALUE = "system.properties";
//    /**
//     * The property name used to specify an URL to the configuration
//     * property file to be used for the created the framework instance.
//    **/
//    public static final String CONFIG_PROPERTIES_PROP = "felix.config.properties";
//    /**
//     * The default name used for the configuration properties file.
//    **/
//    public static final String CONFIG_PROPERTIES_FILE_VALUE = "config.properties";
//    /**
//     * Name of the configuration directory.
//     */
//    public static final String CONFIG_DIRECTORY = "conf";
//
//    private static Framework m_felix = null;
//
//    /**
//     * <p>
//     * This method performs the main task of constructing an framework instance
//     * and starting its execution. The following functions are performed
//     * when invoked:
//     * </p>
//     * <ol>
//     *   <li><i><b>Read the system properties file.<b></i> This is a file
//     *       containing properties to be pushed into <tt>System.setProperty()</tt>
//     *       before starting the framework. This mechanism is mainly shorthand
//     *       for people starting the framework from the command line to avoid having
//     *       to specify a bunch of <tt>-D</tt> system property definitions.
//     *       The only properties defined in this file that will impact the framework's
//     *       behavior are the those concerning setting HTTP proxies, such as
//     *       <tt>http.proxyHost</tt>, <tt>http.proxyPort</tt>, and
//     *       <tt>http.proxyAuth</tt>. Generally speaking, the framework does
//     *       not use system properties at all.
//     *   </li>
//     *   <li><i><b>Perform system property variable substitution on system
//     *       properties.</b></i> Any system properties in the system property
//     *       file whose value adheres to <tt>${&lt;system-prop-name&gt;}</tt>
//     *       syntax will have their value substituted with the appropriate
//     *       system property value.
//     *   </li>
//     *   <li><i><b>Read the framework's configuration property file.</b></i> This is
//     *       a file containing properties used to configure the framework
//     *       instance and to pass configuration information into
//     *       bundles installed into the framework instance. The configuration
//     *       property file is called <tt>config.properties</tt> by default
//     *       and is located in the <tt>conf/</tt> directory of the Felix
//     *       installation directory, which is the parent directory of the
//     *       directory containing the <tt>felix.jar</tt> file. It is possible
//     *       to use a different location for the property file by specifying
//     *       the desired URL using the <tt>felix.config.properties</tt>
//     *       system property; this should be set using the <tt>-D</tt> syntax
//     *       when executing the JVM. If the <tt>config.properties</tt> file
//     *       cannot be found, then default values are used for all configuration
//     *       properties. Refer to the
//     *       <a href="Felix.html#Felix(java.util.Map)"><tt>Felix</tt></a>
//     *       constructor documentation for more information on framework
//     *       configuration properties.
//     *   </li>
//     *   <li><i><b>Perform system property variable substitution on configuration
//     *       properties.</b></i> Any configuration properties whose value adheres to
//     *       <tt>${&lt;system-prop-name&gt;}</tt> syntax will have their value
//     *       substituted with the appropriate system property value.
//     *   </li>
//     *   <li><i><b>Copy configuration properties specified as system properties
//     *       into the set of configuration properties.</b></i> Even though the
//     *       Felix framework does not consult system properties for configuration
//     *       information, sometimes it is convenient to specify them on the command
//     *       line when launching Felix. To make this possible, the Felix launcher
//     *       copies any configuration properties specified as system properties
//     *       into the set of configuration properties passed into Felix.
//     *   </li>
//     *   <li><i><b>Creates and starts a framework instance.</b></i> The configuration
//     *       properties are passed into the Felix constructor and the {{Felix.start()}}
//     *       method is called to start the framework.
//     *   </li>
//     * </ol>
//     * <p>
//     * It should be noted that simply starting an instance of the framework is not
//     * enough to create an interactive session with it. It is necessary to install
//     * and start bundles that provide a some means to interact with the framework;
//     * this is generally done by specifying an "auto-start" property in the
//     * configuration property file. If no bundles providing a means to interact
//     * with the framework are installed or if the configuration property
//     * file cannot be found, the framework will appear to be hung or deadlocked.
//     * This is not the case, it is executing correctly, there is just no way to
//     * interact with it. The default launcher provides two configuration properties
//     * to help you automatically install and/or start bundles, which are:
//     * </p>
//     * <ul>
//     *   <li><tt>felix.auto.install.&lt;n&gt;</tt> - Space-delimited list of
//     *       bundle URLs to automatically install into start level <tt>n</tt> when
//     *       the framework is started. Append a specific start level to this
//     *       property name to assign the bundles' start level
//     *       (e.g., <tt>felix.auto.install.2</tt>); otherwise, bundles are
//     *       installed into the default bundle start level.
//     *   </li>
//     *   <li><tt>felix.auto.start.&lt;n&gt;</tt> - Space-delimited list of
//     *       bundle URLs to automatically install and start into start level
//     *       <tt>n</tt> when the framework is started. Append a
//     *       specific start level to this property name to assign the
//     *       bundles' start level(e.g., <tt>felix.auto.start.2</tt>); otherwise,
//     *       bundles are installed into the default bundle start level.
//     *   </li>
//     * </ul>
//     * <p>
//     * These properties should be specified in the <tt>config.properties</tt>
//     * so that they can be processed by the launcher during the framework
//     * startup process.
//     * </p>
//     * @param argv Accepts a single argument, which is the path to use as the
//     *        framework's bundle cache.
//     * @throws Exception If an error occurs.
//    **/
//    public static void main(String[] args) throws Exception
//    {
//        // We support at most one argument, which is the bundle
//        // cache directory.
//        if (args.length > 1)
//        {
//            System.out.println("Usage: [<bundle-cache-dir>]");
//            System.exit(0);
//        }
//
//        // Load system properties.
//        Main.loadSystemProperties();
//
//        // Read configuration properties.
//        Properties configProps = Main.loadConfigProperties();
//        // If no configuration properties were found, then create
//        // an empty properties object.
//        if (configProps == null)
//        {
//            System.err.println("No " + CONFIG_PROPERTIES_FILE_VALUE + " found.");
//            configProps = new Properties();
//        }
//
//        // Copy framework properties from the system properties.
//        Main.copySystemProperties(configProps);
//
//        // If there is a passed in bundle cache directory, then
//        // that overwrites anything in the config file.
//        if (args.length > 0)
//        {
//            configProps.setProperty(Constants.FRAMEWORK_STORAGE, args[0]);
//        }
//
//        // Create a list for custom framework activators and
//        // add an instance of the auto-activator it for processing
//        // auto-install and auto-start properties. Add this list
//        // to the configuration properties.
//        List list = new ArrayList();
//        list.add(new AutoActivator(configProps));
//        configProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
//
//        // Print welcome banner.
//        System.out.println("\nWelcome to Felix.");
//        System.out.println("=================\n");
//
//        try
//        {
//            // Create an instance and start the framework.
//            m_felix = new Felix(configProps);
//            m_felix.start();
//            // Wait for framework to stop to exit the VM.
//            m_felix.waitForStop(0);
//            System.exit(0);
//        }
//        catch (Exception ex)
//        {
//            System.err.println("Could not create framework: " + ex);
//            ex.printStackTrace();
//            System.exit(-1);
//        }
//    }
//
//    /**
//     * <p>
//     * Loads the properties in the system property file associated with the
//     * framework installation into <tt>System.setProperty()</tt>. These properties
//     * are not directly used by the framework in anyway. By default, the system
//     * property file is located in the <tt>conf/</tt> directory of the Felix
//     * installation directory and is called "<tt>system.properties</tt>". The
//     * installation directory of Felix is assumed to be the parent directory of
//     * the <tt>felix.jar</tt> file as found on the system class path property.
//     * The precise file from which to load system properties can be set by
//     * initializing the "<tt>felix.system.properties</tt>" system property to an
//     * arbitrary URL.
//     * </p>
//    **/
//    public static void loadSystemProperties()
//    {
//        // The system properties file is either specified by a system
//        // property or it is in the same directory as the Felix JAR file.
//        // Try to load it from one of these places.
//
//        // See if the property URL was specified as a property.
//        URL propURL = null;
//        String custom = System.getProperty(SYSTEM_PROPERTIES_PROP);
//        if (custom != null)
//        {
//            try
//            {
//                propURL = new URL(custom);
//            }
//            catch (MalformedURLException ex)
//            {
//                System.err.print("Main: " + ex);
//                return;
//            }
//        }
//        else
//        {
//            // Determine where the configuration directory is by figuring
//            // out where felix.jar is located on the system class path.
//            File confDir = null;
//            String classpath = System.getProperty("java.class.path");
//            int index = classpath.toLowerCase().indexOf("felix.jar");
//            int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
//            if (index >= start)
//            {
//                // Get the path of the felix.jar file.
//                String jarLocation = classpath.substring(start, index);
//                // Calculate the conf directory based on the parent
//                // directory of the felix.jar directory.
//                confDir = new File(
//                    new File(new File(jarLocation).getAbsolutePath()).getParent(),
//                    CONFIG_DIRECTORY);
//            }
//            else
//            {
//                // Can't figure it out so use the current directory as default.
//                confDir = new File(System.getProperty("user.dir"), CONFIG_DIRECTORY);
//            }
//
//            try
//            {
//                propURL = new File(confDir, SYSTEM_PROPERTIES_FILE_VALUE).toURL();
//            }
//            catch (MalformedURLException ex)
//            {
//                System.err.print("Main: " + ex);
//                return;
//            }
//        }
//
//        // Read the properties file.
//        Properties props = new Properties();
//        InputStream is = null;
//        try
//        {
//            is = propURL.openConnection().getInputStream();
//            props.load(is);
//            is.close();
//        }
//        catch (FileNotFoundException ex)
//        {
//            // Ignore file not found.
//        }
//        catch (Exception ex)
//        {
//            System.err.println(
//                "Main: Error loading system properties from " + propURL);
//            System.err.println("Main: " + ex);
//            try
//            {
//                if (is != null) is.close();
//            }
//            catch (IOException ex2)
//            {
//                // Nothing we can do.
//            }
//            return;
//        }
//
//        // Perform variable substitution on specified properties.
//        for (Enumeration e = props.propertyNames(); e.hasMoreElements(); )
//        {
//            String name = (String) e.nextElement();
//            System.setProperty(name,
//                Util.substVars(props.getProperty(name), name, null, null));
//        }
//    }
//
//    /**
//     * <p>
//     * Loads the configuration properties in the configuration property file
//     * associated with the framework installation; these properties
//     * are accessible to the framework and to bundles and are intended
//     * for configuration purposes. By default, the configuration property
//     * file is located in the <tt>conf/</tt> directory of the Felix
//     * installation directory and is called "<tt>config.properties</tt>".
//     * The installation directory of Felix is assumed to be the parent
//     * directory of the <tt>felix.jar</tt> file as found on the system class
//     * path property. The precise file from which to load configuration
//     * properties can be set by initializing the "<tt>felix.config.properties</tt>"
//     * system property to an arbitrary URL.
//     * </p>
//     * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
//    **/
//    public static Properties loadConfigProperties()
//    {
//        // The config properties file is either specified by a system
//        // property or it is in the conf/ directory of the Felix
//        // installation directory.  Try to load it from one of these
//        // places.
//
//        // See if the property URL was specified as a property.
//        URL propURL = null;
//        String custom = System.getProperty(CONFIG_PROPERTIES_PROP);
//        if (custom != null)
//        {
//            try
//            {
//                propURL = new URL(custom);
//            }
//            catch (MalformedURLException ex)
//            {
//                System.err.print("Main: " + ex);
//                return null;
//            }
//        }
//        else
//        {
//            // Determine where the configuration directory is by figuring
//            // out where felix.jar is located on the system class path.
//            File confDir = null;
//            String classpath = System.getProperty("java.class.path");
//            int index = classpath.toLowerCase().indexOf("felix.jar");
//            int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
//            if (index >= start)
//            {
//                // Get the path of the felix.jar file.
//                String jarLocation = classpath.substring(start, index);
//                // Calculate the conf directory based on the parent
//                // directory of the felix.jar directory.
//                confDir = new File(
//                    new File(new File(jarLocation).getAbsolutePath()).getParent(),
//                    CONFIG_DIRECTORY);
//            }
//            else
//            {
//                // Can't figure it out so use the current directory as default.
//                confDir = new File(System.getProperty("user.dir"), CONFIG_DIRECTORY);
//            }
//
//            try
//            {
//                propURL = new File(confDir, CONFIG_PROPERTIES_FILE_VALUE).toURL();
//            }
//            catch (MalformedURLException ex)
//            {
//                System.err.print("Main: " + ex);
//                return null;
//            }
//        }
//
//        // Read the properties file.
//        Properties props = new Properties();
//        InputStream is = null;
//        try
//        {
//            // Try to load config.properties.
//            is = propURL.openConnection().getInputStream();
//            props.load(is);
//            is.close();
//        }
//        catch (Exception ex)
//        {
//            // Try to close input stream if we have one.
//            try
//            {
//                if (is != null) is.close();
//            }
//            catch (IOException ex2)
//            {
//                // Nothing we can do.
//            }
//
//            return null;
//        }
//
//        // Perform variable substitution for system properties.
//        for (Enumeration e = props.propertyNames(); e.hasMoreElements(); )
//        {
//            String name = (String) e.nextElement();
//            props.setProperty(name,
//                Util.substVars(props.getProperty(name), name, null, props));
//        }
//
//        return props;
//    }
//
//    public static void copySystemProperties(Properties configProps)
//    {
//        for (Enumeration e = System.getProperties().propertyNames();
//             e.hasMoreElements(); )
//        {
//            String key = (String) e.nextElement();
//            if (key.startsWith("felix.") || key.startsWith("org.osgi.framework."))
//            {
//                configProps.setProperty(key, System.getProperty(key));
//            }
//        }
//    }
//}
